#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_scalar_block_layout : enable
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_buffer_reference2 : require
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
#extension GL_ARB_shader_clock : enable



#include "../../../../core/shader_std.h"
#include "ray_std.h"





//模型顶点类型
layout(buffer_reference, scalar) readonly buffer B_Vertices {S_Vert V[]; }; 
layout(buffer_reference, scalar) readonly buffer B_UV {vec2 UV[]; };
layout(buffer_reference, scalar) readonly buffer B_Indexs {uvec3 I[]; };
layout(buffer_reference, scalar) readonly buffer B_Faces {S_FaceElement Element[]; };

//全局统一数据类型
//layout(buffer_reference, scalar, align=4) readonly buffer B_MaterialID {uint MID[]; };
//layout(buffer_reference, scalar, std430) readonly buffer B_MaterialRef {S_Material M[]; };




layout(binding = 0, set = 0) uniform accelerationStructureEXT topLAS;
layout(binding = 2, set = 0) uniform CameraProp {
	mat4 projInverse;
	mat4 viewInverse;
	mat4 projMat;
	mat4 viewMat;
} cam;

layout(binding = DEF_RenderFrameBindID, set = 0, scalar) uniform FrameProp {
	GLSL_RenderFrame renderFrame;
};

layout(binding = DEF_ObMeshBindID, scalar)        readonly buffer B_ObjMesh { S_ObMesh m_Address[];} ObMesh;

//全局统一数据类型
layout(binding = DEF_MaterialsBindID, scalar)     readonly buffer    B_Material { S_Material m_Material[];};
layout(binding = DEF_TexturesBindID)              uniform  sampler2D Ts[];
layout(binding = DEF_ParallelLightBindID, scalar) readonly buffer    B_LigthParallel {S_LigthParallel L[]; } LigthParallel;


layout(binding = 10, set = 0) buffer Vertices { float v[]; } vertices;


layout(location = 0) rayPayloadInEXT S_Ray hitValue;

layout(location = 0) callableDataEXT S_SceneDataCall callSceneData;
layout(location = 1) callableDataEXT S_Material callMaterial;

hitAttributeEXT vec2 attribs;

//gl_GeometryIndexEXT
vec3 f_Material(vec3 color, in S_Material material){
	vec3 reColor = mix(material.m_color, color, 0.5);
	//return material.m_color;
	//return vec3(1,0,1);
	return reColor;
}


void main(){
	S_ObMesh objResource = ObMesh.m_Address[gl_InstanceCustomIndexEXT];

	//模型顶点元素数据
	B_Vertices mesh_vert  = B_Vertices(objResource.m_AddressVertex);
	B_UV       uv_coord   = B_UV(objResource.m_AddressUV);
	B_Indexs   uv_index   = B_Indexs(objResource.m_AddressUVIndex);
	B_Indexs   mesh_index = B_Indexs(objResource.m_AddressIndex);
	B_Faces    mesh_face  = B_Faces(objResource.m_AddressFaces);

	//面元素
	S_FaceElement Element = mesh_face.Element[gl_PrimitiveID];
	
	//索引材质
	S_Material material = m_Material[ Element.MaterialID ];
	//S_Material material = m_Material[ 1 ];
	
	hitValue.Color = vec3(0,1,0);
	++hitValue.Depth;
	return;
	

	uvec3 faceIndex = mesh_index.I[gl_PrimitiveID];
	uvec3 uvIndex = uv_index.I[gl_PrimitiveID];


	vec2 v0_uv = uv_coord.UV[faceIndex.x];
	vec2 v1_uv = uv_coord.UV[faceIndex.y];
	vec2 v2_uv = uv_coord.UV[faceIndex.z];

	//uvec3 faceIndex = uvec3(1,1,1);
	vec3 v0 = mesh_vert.V[faceIndex.x].vert;
	vec3 v1 = mesh_vert.V[faceIndex.y].vert;
	vec3 v2 = mesh_vert.V[faceIndex.z].vert;
	
	vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
	//vec3 normal = normalize(cross(v1-v0, v2-v0));
	vec3 normal = mesh_vert.V[faceIndex.x].normal * barycentrics.x + mesh_vert.V[faceIndex.y].normal * barycentrics.y + mesh_vert.V[faceIndex.z].normal * barycentrics.z;
	//normal = normal * mat3(gl_WorldToObjectEXT);
	//normal = normal * mat3(gl_ObjectToWorldEXT);
	uint64_t id = material.m_colorTex;
	//sampler2D(id);
	
	uint seed = f_tea(gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x, int(clockARB()) ); 
	vec3 noise = vec3(f_rnd(seed), f_rnd(seed), f_rnd(seed)) * 2 - 0.5;


	//float l = length(noise);
	vec3 rv = normalize(normal + noise * 0.5);
	
	//vec3 lightDir = normalize(normalize(vec3(0.5,0.5,0.5)) + noise * 0.1);
	//vec3 rv = reflect(gl_WorldRayDirectionEXT, normal);
	//vec3 rv = refract(gl_WorldRayDirectionEXT, normal, 0.4);

	// Shadow casting
	float tmin = 0.001;
	float tmax = 10000.0;
	//vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;
	vec3 origin = v0 * barycentrics.x + v1 * barycentrics.y + v2 * barycentrics.z;
	origin = vec3(gl_ObjectToWorldEXT * vec4(origin, 1));
	//origin = vec3(gl_ObjectToWorld3x4EXT * origin);

	uint RayDepth = 0;
	float intensity = 1;
	if(hitValue.Depth > 0){
		intensity = length(origin - hitValue.Origin);
	}
	
	//uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT;
	uint flags = gl_RayFlagsOpaqueEXT;
	uint cullMask = 0xff;
	vec3 oldColor = hitValue.Color;
	RayDepth = hitValue.Depth;
	
	vertices.v[hitValue.Depth] = hitValue.RayType + 1;
	//是否定向检测光照
	if(hitValue.Depth < renderFrame.m_BouncesNum ){
		++hitValue.Depth;

		switch(hitValue.RayType){
			case DEF_RayType:{
				normal = normal * mat3(gl_WorldToObjectEXT);
				//normal = normal * mat3(gl_ObjectToWorldEXT);
				vec3 rv = normalize(normal + noise * material.m_roughness);

				rv = reflect(gl_WorldRayDirectionEXT, rv);
				if(dot(rv, normal) >= -0.1){
					hitValue.Origin = origin;
					//hitValue.Dir = normalize(rv);
					
					
					
					//traceRayEXT(topLAS, flags, cullMask, 0, 0, 1, hitValue.Origin, tmin, hitValue.Dir, tmax, 0);
					
					if(RayDepth > 0) {
						hitValue.Dis *= 1 / ((gl_HitTEXT+1) * 1);
					}

					//计算材质
					if ( material.m_shaderIndex != -1 ) {
						callSceneData.Normal = normal;
						//callSceneData.MaterialID = Element.MaterialID;

						callMaterial = m_Material[ Element.MaterialID ];
						//executeCallableEXT(Element.ShaderType, 0);
						//executeCallableEXT(0, 0);

						hitValue.Color = callSceneData.Color;
						//hitValue.Color = vec3(1.0,0.0,1.0);
					}
					else {
						hitValue.Color = f_Material(hitValue.Color, material);
					}
					//hitValue.Color = vec3(1.0,0.0,1.0);
				}
				
				break;
			}
			case DEF_LigthRayType:{
				
				hitValue.Origin = origin;
				//hitValue.Dir = normalize(rv);
				
				normal = normal * mat3(gl_ObjectToWorldEXT);
				//跳到定向光返回
				hitValue.RayType = DEF_LigthReturnRayType;
				vec3 lightDir = normalize(LigthParallel.L[0].m_dir + noise * LigthParallel.L[0].m_diffusivity);
				
				hitValue.Normal = normalize(normal);
				
				hitValue.Color = vec3(0.0,1.0,0.0);
				float d = dot(lightDir, normal);
				//hitValue.Dir *= max(0, d);
				//hitValue.Dir = normalize(vec3(1,1,1));
				//hitValue.Dir = lightDir;
				
				
				
				if(d > 0.1){
					traceRayEXT(topLAS, flags, cullMask, 0, 0, 0, hitValue.Origin, tmin, lightDir, tmax, 0);
				}

				hitValue.Dis *= 0.5;
				//lightDir = normalize(vec3(1,1,1) + noise * LigthParallel.L[0].m_diffusivity * 0.5);
				d = dot(lightDir, normal);
				
				break;
			}
			case DEF_LigthReturnRayType:{
				//跳到物体射线追踪
				hitValue.Dis *= 0.03;
				break;
			}
		}
	}
	
	if(hitValue.Depth == 64){
		//hitValue.Dis = 3;
	}
	
}








